package com.stone.serverless.auth.handler;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import javax.servlet.http.Cookie;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: TODO
 * @Author: MECHREVO
 * @Date: 2022/1/27 9:50
 * @Version: 1.0.0
 */
public class RequestResponseInvokeHandler implements InvocationHandler, MethodInterceptor {
    private Object target;

    public RequestResponseInvokeHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return this.proxy(proxy, method, args);
    }

    public Object proxy(Object proxy, Method method, Object[] args) throws Throwable {

        Class<?> aClass = target.getClass();
        Class<?>[] parameterTypes = method.getParameterTypes();

        String name = method.getName();
        Method[] declaredMethods = aClass.getDeclaredMethods();
        Method invokeMethod = null;
        for (Method m : declaredMethods) {
            if (m.getName().equals(name)) {
                //匹配参数个数 与类型
                Class<?>[] parameterTypes1 = m.getParameterTypes();
                if (parameterTypes1.length != parameterTypes.length) {
                    continue;
                }
                boolean mat = true;
                for (int i = 0; i < parameterTypes.length; i++) {
                    Class<?> arg = parameterTypes[i];
                    Class<?> aClass1 = parameterTypes1[i];
                    if (!arg.getName().equals(aClass1.getName())) {
                        mat = false;
                    }
                }
                if (!mat) {
                    continue;
                }
                invokeMethod = m;
                break;
            }
        }
        if (null == invokeMethod) {
            return null;
        }

        Object invoke = ReflectUtil.invoke(target, invokeMethod, args);
        if (invokeMethod.getName().equals("getCookies")) {
            if (ObjectUtil.isNotNull(invoke)) {

                Object[] cookies = (Object[]) invoke;
                List<Cookie> cookies1 = new ArrayList<>();
                if (cookies.length > 0) {
                    for (Object c : cookies) {
                        Cookie cookie = new Cookie((String) ReflectUtil.getFieldValue(c,"name"),
                                (String) ReflectUtil.getFieldValue(c,"value"));
                        cookies1.add(cookie);
                    }
                }
                return cookies1.stream().toArray(Cookie[]::new);
            }
        }
        return invoke;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        return this.proxy(o, method, objects);
    }
}
